﻿

using AlphaNN.Forms;

namespace SSS.AlphaNN.Components
{

    using System;
    using System.Collections.Generic;
    using AlphaNN.Forms;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Xml;
    using System.Xml.Linq;
    using System.Linq;

    //Эта часть кода моя=) Не трогать!!! Или править но с донесением что сделано=)
    public partial class WorkGround
    {

        /// <summary>
        /// Имя файла в котором сохранялась нейронная сеть
        /// </summary>
        public string FileName
        {
            set;
            get;
        }

        /// <summary>	
        /// Взятие списка нейронов 
        /// </summary>
        public List<Neuron> ListNeuron
        {
            get
            {
                return dummies.Where( x => x is Neuron ).Select( x => (Neuron)x ).ToList();
            }
        }

        /// <summary>
        /// getter and setter списка Приёмников
        /// </summary>
        public List<Sink> ListSink
        {
            get
            {
                return dummies.Where( x => x is Sink ).Select( x => (Sink)x ).ToList();
            }
        }

        /// <summary>
        /// Взятие списка источников and input list sources
        /// </summary>
        public List<Source> ListSource
        {
            get
            {
                return dummies.Where( x => x is Source ).Select( x => (Source)x ).ToList();
            }
        }


        /// <summary>
        /// Взятие списка связей and input list links
        /// </summary>
        public List<Link> GetListLink
        {
            get
            {
                return new List<Link>( links );
            }
            set
            {
                links = new List<Link>( value );
            }
        }

        /// <summary>
        /// Взятие учителя
        /// </summary>
        public Teacher GetListTeacher
        {
            get
            {
                return (Teacher)( dummies.Where( x => x is Teacher ).ToArray() )[0];
            }

        }

        /// <summary>
        /// Берём состояние рабочей области
        /// </summary>
        public WorkGroundState StateWorkGround
        {
            get
            {
                return _wrkGroundState;
            }
            set
            {
                _wrkGroundState = value;
            }
        }

        //Смотрю на код ниже и думаю - и кто ЭТО писал?=)
        /// <summary>
        /// Добавление создаваемого объекта в один из списков
        /// </summary>
        /// <param name="objectCreates">Создаваемый объект</param>
        private void AddObjectInList( Object dummy )
        {
            if ( ( dummy is DataMedium ) )
            {
                //это для источника и приёмника
                string numberSlot = "";
                //определяем количество слотов
                if ( InputBoxForm.Query( ( ( dummy is Sink )?"Приёмник: ":( dummy is Source )?"Источник: ":"Учитель: " )+" Введите количество входных переменных",
                                   "Количество",
                                   ref numberSlot ) )
                {


                    int countSlots = 1;
                    bool b = int.TryParse( numberSlot, out countSlots );
                    if ( dummy is Source )
                    {
                        //проверка на корректность количества слотов
                        if ( !b && ( countSlots > 8 || countSlots < 1 ) )
                        {
                            ( (DataMedium)dummy ).countSignal = 1;
                            MessageBox.Show(
                                "Ошибка!!! Количество входных параметров может быть только меньше 8 и больше 0",
                                "Ошибка",
                                MessageBoxButtons.OK, MessageBoxIcon.Error );
                        }
                        else
                        {
                            ( (DataMedium)dummy ).countSignal = countSlots;
                        }
                    }
                    else
                    {
                        if ( dummy is Sink )
                        {
                            //проверка на корректность количества слотов
                            if ( !b && ( countSlots != 1 ) )
                            {
                                ( (DataMedium)dummy ).countSignal = 1;
                                MessageBox.Show(
                                    "Ошибка!!! Количество входных параметров может быть 1",
                                    "Ошибка",
                                    MessageBoxButtons.OK, MessageBoxIcon.Error );
                            }
                            else
                            {
                                ( (DataMedium)dummy ).countSignal = countSlots;
                            }
                        }
                    }


                }
            }


        }

        private void ShowDialogProperties( Object dummy )
        {
            WorkingWithComponent( dummy, new Action<Object>[]
                                            {
                                x=>
                                {
                                    PropertiesNeuronForm pf=new PropertiesNeuronForm((Neuron)x);
                                    pf.ShowDialog();
                                },
                                x=>
                                {
                                    PropertiesDBForm pf=new PropertiesDBForm((Source)x);
                                    pf.ShowDialog();
                                },
                                x=>
                                {
                                    PropertiesFOForm pf=new PropertiesFOForm((Sink)x);
                                    pf.ShowDialog();
                                },
                                x=>
                                {
                                    PropertiesDBForm pf=new PropertiesDBForm((Teacher)x);
                                    pf.ShowDialog();
                                }   
        } );
        }

        /// <summary>
        /// Что бы работать со всеми компонентами
        /// </summary>
        /// <param name="dummy">ОБъект  с типом neuron, teacher, source, sink</param>
        /// <param name="actions">Действия для объектов</param>
        private void WorkingWithComponent( Object dummy, Action<Object>[] actions )
        {
            if ( dummy is Neuron )
            {
                actions[0]( dummy );
            }

            if ( dummy is Source )
            {
                actions[1]( dummy );
            }

            if ( dummy is Sink )
            {
                actions[2]( dummy );
            }

            if ( dummy is Teacher )
            {
                actions[3]( dummy );
            }
        }

        /// <summary>
        /// Перерисовка
        /// </summary>
        public void ReDraw()
        {
            List<Dummy> liDummies = new List<Dummy>();

            dummies = liDummies;

            WorkGround_Paint( this, new PaintEventArgs( this.CreateGraphics(), new Rectangle( this.Location, this.Size ) ) );
        }

        /// <summary>
        /// Открытие формы свойств для линии
        /// </summary>
        /// <param name="link">Линия для которой вызывается панель свойств</param>
        private void ShowDialogForLink( Link link )
        {
            string str = link.ValueLink.ToString();
            if ( InputBoxForm.Query( "Ввод данных", "Введите или исправте вес связи", ref str ) )
            {
                double outRes = link.ValueLink;
                if ( double.TryParse( str, out outRes ) )
                    link.ValueLink = outRes;
            }
        }
    

        public void SaveInXml( string path )
        {
            //XDocument xdoc = GetXmlDocument();
            //  xdoc.Save(path);
        }
        
        /// <summary>
        /// Поиск и извлечение из списка компонентов нейронной сети нужного компонента для связей в Slot
        /// </summary>
        /// <param name="liDummy">Список компонентов нейронной сети</param>
        /// <param name="dummyIdentificator">Идентификатор нужного компонента нейронной сети</param>
        /// <returns>Компонет нейронной сети в Slot</returns>
        private static Dummy GetObjectForSlot( List<Dummy> liDummy, int dummyIdentificator )
        {
            foreach ( Dummy dummy in liDummy )
                if ( dummy.Identificator == dummyIdentificator )
                    return dummy;

            return null;
        }

        /// <summary>
        /// Свойство определяющее можно ли запускать эту нейронную сеть
        /// </summary>
        public bool IsRun
        {
            get
            {
                bool a= ListSink.Count > 0
                       && ListSource.Count > 0;

               List<Dummy> dic=new List<Dummy>();
                foreach (Link link in links)
                {
                    if (!dic.Contains(link.componentSlot1))
                    {
                        dic.Add(link.componentSlot1);
                    }

                    if (!dic.Contains(link.componentSlot2))
                    {
                        dic.Add(link.componentSlot2);
                    }
                }


                a &= dic.Count == dummies.Count-((GetListTeacher!=null)?1:0);

                if ( a )
                {
                    bool b = links.Count > 0;
                    if ( b )
                    {
                        Func<string, bool> c=x =>
                            x != null && x!= String.Empty && x != "";
                        return c( ListSource[0].PathFileDb )&&c( ListSource[0].Query );
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
        }

        /// <summary>
        /// Свойство определяющее можно ли обучать эту нейронную сеть
        /// </summary>
        public bool IsTeach
        {
            get
            {
                return dummies.Where( x => x is Teacher ).Count() > 0&&IsRun;
            }
        }

        /// <summary>
        /// Свойство определяющее соединенны ли между собой источник и приёмник на прямую
        /// </summary>
        public bool linkConnectionSinkAndSource
        {
            get
            {
                return links.Where( x => ( x.componentSlot1 is Source ) && ( x.componentSlot2 is Sink ) ).Count()==links.Count;
            }
        }
    }


}
